import mapSettings from './mapSettings.js'

import utils from '../utils/index.js'

// 魔塔游戏的基础对象
class MTObj extends Laya.Sprite {
  constructor (options = {}, parent = null) {
    super()

    this.parentMapItem = parent

    this.init(options)
  }

  /* @section init 初始化 */

  // 数据初始化
  init (options = {}) {
    // 获取各种设定
    this.type = 'Obj'
    // 原始类型还是要记录一下
    this.rootType = options.type
    this.id = options.id
    this.pass = options.pass
    this.vision = options.vision
    this.layer = options.layer
    this.src = this.getStandardSrc(options.src)
    this.animations = options.animations

    // 动画前缀名获取，需要区分Autotile
    if (this.rootType === 'Autotile') {
      // Autotile有着特殊的动画前缀名
      const ruleName = this.getAutotileRule(this.src, options.isFrames)
      this.aniHead = this.id + '_' + ruleName + '_'
    }
    else {
      // 其他情况前缀名正常
      this.aniHead = this.id + '_'
    }

    // 位置设定
    // 宽高要么指定，如果没指定，默认为32x32
    this.width = typeof options.width === 'number' ? options.width : mapSettings.MAP_ITEM_SIZE
    this.height = typeof options.height === 'number' ? options.height : mapSettings.MAP_ITEM_SIZE
    // 偏移量若没有指定，默认为0
    this.top = typeof options.top === 'number' ? options.top : 0
    this.left = typeof options.left === 'number' ? options.left : 0
  }

  /* 
    指定引擎属性
    layer 被添加到的层
  */
  initLayas (layer) {
    // 宽高已经在init函数中设定

    // 指定绘制优先级
    this.zOrder = this.layer

    // 初始化位置
    const pos = this.getPos()
    this.pos(pos.x, pos.y)
    // 添加到层中
    layer.addChild(this)
  }

  // 初始化资源，执行这个函数后，对象才能显示出来
  async initSrc () {
    const aniKeys = Object.keys(this.animations)

    if (aniKeys.length !== 0) {
      // 需要创建动画
      await this.initAnimations(aniKeys)
      // 播放默认动画
      this.playAnimation('default')
    }
    else {
      // 指定texture即可
      this.texture = this.src
    }
  }

  // 初始化动画资源
  initAnimations (aniKeys = null) {
    return new Promise((resolve, reject) => {
      if (!aniKeys) {
        const aniKeys = Object.keys(this.animations)
      }
      
      // 创建动画对象
      this.aniObj = new Laya.Animation()
      this.addChild(this.aniObj)  

      // 读取动画图集
      const atlasSrc = this.getAtlasSrc(this.animations[aniKeys[0]].srcList[0])
      try {
        this.aniObj.loadAtlas(atlasSrc, Laya.Handler.create(this, () => {
          // 循环创建动画
          for (let key in this.animations) {
            this.setAnimation(key)
          }
          // 
          resolve()
        }))            
      }
      catch (err) {
        reject(err)
      }
    })
  }

  /* @section on 生命周期方法 */
  

  /* @section get 获取信息 */

  // 获取单位的位置
  getPos () {
    const item = this.parentMapItem
    // 以后要加上偏移定位参数
    return {
      x: item.colIndex * mapSettings.MAP_ITEM_SIZE + this.left,
      y: item.rowIndex * mapSettings.MAP_ITEM_SIZE + this.top
    }
  }

  // 获取图集地址
  getAtlasSrc (src) {
    let srcArr = src.split('/')
    // 删掉文件名称
    srcArr.splice(srcArr.length - 1, 1)
    let result = srcArr.join('/')

    // 补充前缀和后缀
    result = 'res/atlas' + result + '.atlas'
    return result
  }

  // 根据参考资源地址，获取Autotile的类型名称
  getAutotileRule (src, isFrames) {
    // 获取后缀
    const tail = utils.str.getFileTail(src)
    // 去除后缀
    src = utils.str.cutFileTail(src)
    // 下划线分割
    let srcArr = src.split('_')
    const len = srcArr.length
    // 倒数第一个为数字
    if (isFrames) {
      // 对于有动画的Autotile,倒数第二位是名称
      return srcArr[len - 2]
    }
    // 否则是最后一位
    return srcArr[len - 1]
  }

  // 获取规范化的资源地址，去除第一位/
  getStandardSrc (src) {
    if (typeof src === 'string' && src[0] === '/') {
      return src.slice(1)
    }
    return src
  }

  // 获取规范化的资源地址列表
  getStandardSrcList (srcList) {
    const len = srcList.length
    for (let i = 0; i < len; i++) {
      srcList[i] = this.getStandardSrc(srcList[i])
    }
    return srcList
  }

  /* @section set 设置方法 */

  // 设置一个动画
  setAnimation (animationKey) {
    const animation = this.animations[animationKey]
    if (animation) {
      const srcList = this.getStandardSrcList(animation.srcList)
      Laya.Animation.createFrames(srcList, this.aniHead + animationKey)
    }
  }

  /* @section method 常规行为 */

  // 播放一个动画
  playAnimation (animationKey, start = 0, isLoop = true) {
    if (this.aniObj) {
      this.aniObj.play(start, isLoop, this.aniHead + animationKey)
    }
  }
}

export default MTObj